﻿using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MyCompany.MyProject.Common;
using MyCompany.MyProject.Common.Helper;
using MyCompany.MyProject.Common.HttpContextUser;
using MyCompany.MyProject.Extensions.Auth;
using MyCompany.MyProject.Extensions.Helper;
using MyCompany.MyProject.IService;
using MyCompany.MyProject.Model;
using MyCompany.MyProject.Model.DTO;
using MyCompany.MyProject.Model.Models;
using MyCompany.MyProject.Repository.UnitOfWork;
using MyCompany.MyProject.WebApi.ModelDto.PermissionDto;
using Newtonsoft.Json;
using System.Text;

namespace MyCompany.MyProject.WebApi.Controllers
{
    /// <summary>
    /// 菜单管理
    /// </summary>
    public class PermissionController : BasePermissionApiController
    {
        private readonly IMapper _mapper;
        private readonly IBaseService<Permission> _permissionService;
        private readonly IBaseService<Modules> _moduleService;
        private readonly IUser _user;
        private readonly IRoleModulePermissionServices _roleModulePermissionServices;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IUserRoleService _userRoleService;
        private readonly IHostEnvironment _env;
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly PermissionRequirement _requirement;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="mapper"></param>
        /// <param name="permissionService"></param>
        /// <param name="moduleService"></param>
        /// <param name="user"></param>
        /// <param name="roleModulePermissionServices"></param>
        /// <param name="httpContextAccessor"></param>
        /// <param name="userRoleService"></param>
        /// <param name="env"></param>
        /// <param name="unitOfWorkManage"></param>
        /// <param name="requirement"></param>
        public PermissionController(IMapper mapper, IBaseService<Permission> permissionService, IBaseService<Modules> moduleService,
            IUser user, IRoleModulePermissionServices roleModulePermissionServices, IHttpContextAccessor httpContextAccessor, IUserRoleService userRoleService, IHostEnvironment env,
            IUnitOfWorkManage unitOfWorkManage, PermissionRequirement requirement)
        {
            _mapper = mapper;
            _permissionService = permissionService;
            _moduleService = moduleService;
            _user = user;
            _roleModulePermissionServices = roleModulePermissionServices;
            _httpContextAccessor = httpContextAccessor;
            _userRoleService = userRoleService;
            _env = env;
            _unitOfWorkManage = unitOfWorkManage;
            _requirement = requirement;
        }

        /// <summary>
        /// 获取菜单
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<PageModel<PermissionVo>>> Get(int pageIndex = 1, int pageSize = 10, string key = "")
        {
            PageModel<PermissionVo> permissions = new PageModel<PermissionVo>();
            var data = await _permissionService.QueryPage(null, pageIndex, pageSize, "Id desc"); ;
            permissions = data.ConvertTo<PermissionVo>(_mapper);

            var apis = await _moduleService.Query();
            var permissionView = permissions.Data;
            var permissionAll = await _permissionService.Query();

            foreach (var item in permissionView)
            {
                List<long> pidArr = new()
                {
                    item.Pid
                };
                if (item.Pid > 0)
                {
                    pidArr.Add(0);
                }
                var parent = permissionAll.FirstOrDefault(d => d.Id == item.Pid);
                while (parent != null)
                {
                    pidArr.Add(parent.Id);
                    parent = permissionAll.FirstOrDefault(d => d.Id == parent.Pid);
                }

                item.PidArr = pidArr.OrderBy(d => d).Distinct().ToList();

                foreach (var pid in item.PidArr)
                {
                    var per = permissionAll.FirstOrDefault(d => d.Id == pid);
                    item.PnameArr?.Add((per != null ? per.Name : "根节点") + "/");
                }
                item.MName = apis.FirstOrDefault(d => d.Id == item.Mid)?.LinkUrl;
            }

            permissions.Data = permissionView;

            return permissions.DataCount >= 0 ? Success(permissions, "获取成功") : Failed<PageModel<PermissionVo>>("获取失败");
        }

        /// <summary>
        /// 查询属性table
        /// </summary>
        /// <param name="f"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<List<PermissionVo>>> GetTreeTable(long f = 0, string key = "")
        {
            List<PermissionVo> permissions = new List<PermissionVo>();
            var apiList = await _moduleService.Query();
            var permissionList = await _permissionService.Query();

            if (!string.IsNullOrEmpty(key))
            {
                permissions = _mapper.Map<List<PermissionVo>>( permissionList.Where(d => d.Name!.Contains(key) || d.Code!.Contains(key)).OrderBy(i => i.OrderSort).ToList());
            }
            else
            {
                permissions = _mapper.Map<List<PermissionVo>>( permissionList.Where(i => i.Pid == f).OrderBy(i => i.OrderSort).ToList());
            }
            foreach (var item in permissions)
            {
                List<long> pidArr = new List<long>();
                var parent = permissionList.FirstOrDefault(d => d.Id == item.Pid);

                while (parent != null)
                {
                    pidArr.Add(parent.Id);
                    parent = permissionList.FirstOrDefault(d => d.Id == parent.Pid);
                }
                pidArr.Reverse();
                pidArr.Insert(0, 0);
                item.PidArr = pidArr;
                item.MName = apiList.FirstOrDefault(d => d.Id == item.Mid)?.LinkUrl;
                item.hasChildren = permissionList.Where(d => d.Pid == item.Id).Any();
            }
            return Success(permissions, "获取成功");
        }

        /// <summary>
        /// 获取菜单树
        /// </summary>
        /// <param name="pid"></param>
        /// <param name="needbtn"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<PermissionTree>> GetPermissionTree(long pid = 0, bool needbtn = false)
        {
            var permissions = await _permissionService.Query();
            var permissionTree = (from child in permissions
                                  where child.IsDeleted == false
                                  orderby child.Id
                                  select new PermissionTree
                                  {
                                      value = child.Id,
                                      label = child.Name,
                                      Pid = child.Pid,
                                      isbtn = child.IsButton,
                                      order = child.OrderSort
                                  }).ToList();
            PermissionTree root = new PermissionTree
            {
                value = 0,
                Pid = 0,
                label = "根节点"
            };
            permissionTree = permissionTree.OrderBy(i => i.order).ToList();
            RecursionHelper.LoopToAppendChildren(permissionTree, root, pid, needbtn);
            return Success(root, "获取成功");
        }

        /// <summary>
        /// 新增菜单
        /// </summary>
        /// <param name="permission"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<MessageModel<string>> Add([FromBody] PermissionVo permission)
        {
            if (permission == null)
            {
                return Failed<string>("参数错误");
            }
            permission.CreateId = _user.ID;
            permission.CreateBy = _user.Name;
            permission.CreateTime = DateTime.Now;
            var newPermission = _mapper.Map<Permission>(permission);
            var id = await _permissionService.Add(newPermission);
            return id > 0 ? Success(id.ToString(), "添加成功") : Failed<string>("添加失败");
        }

        /// <summary>
        /// 更新菜单
        /// </summary>
        /// <param name="permission"></param>
        /// <returns></returns>
        [HttpPut]
        public async Task<MessageModel<string>> Update([FromBody] PermissionVo permission)
        {
            if (permission == null || permission.Id <= 0)
            {
                return Failed<string>("参数错误");
            }
            var oldPermission = await _permissionService.QueryById(permission.Id);
            if (oldPermission == null)
            {
                return Failed<string>("菜单不存在");
            }
            var data = new MessageModel<string>();
            permission.ModifyId = _user.ID;
            permission.ModifyBy = _user.Name;
            permission.ModifyTime = DateTime.Now;
            var updateSuccess = await _permissionService.Update(_mapper.Map<Permission>( permission));
            await _roleModulePermissionServices.UpdateModuleId(permission.Id, permission.Mid);
            return updateSuccess ? Success(permission.Id.ToString(), "更新成功") : Failed<string>("更新失败");
        }

        /// <summary>
        /// 删除菜单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpDelete("{id}")]
        public async Task<MessageModel<string>> Delete(long id)
        {
            if (id <= 0)
            {
                return Failed<string>("参数错误");
            }
            var oldPermission = await _permissionService.QueryById(id);
            if (oldPermission == null)
            {
                return Failed<string>("菜单不存在");
            }
            var hasChildren = (await _permissionService.Query(d => d.Pid == id)).Any();
            if (hasChildren)
            {
                return Failed<string>("请先删除子节点");
            }
            oldPermission.IsDeleted = true;
            var deleteSuccess = await _permissionService.Update(oldPermission);

            return deleteSuccess ? Success(id.ToString(), "删除成功") : Failed<string>("删除失败");
        }

        /// <summary>
        /// 获取动态路由菜单
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        [HttpGet]
        [AllowAnonymous]
        public async Task<MessageModel<NavigationBar>> GetNavigationBar(long uid)
        {
            var data = new MessageModel<NavigationBar>();
            var token = _httpContextAccessor.HttpContext?.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
            if (string.IsNullOrEmpty(token))
            {
                data.msg = "获取用户信息失败";
                data.status = 401;
                return data;
            }
            long uidInHttpcontext = JwtHelper.SerializeJwt(token).Uid;
            var roleList = await _userRoleService.Query(i => i.UserId == uid);
            var roleIds = roleList.Select(i => i.RoleId).Distinct().ToList();
            if (uid > 0 && uid == uidInHttpcontext)
            {
                if (roleIds.Any())
                {
                    var roleModulePermissions = await _roleModulePermissionServices.Query(i => roleIds.Contains(i.RoleId));
                    var pids = roleModulePermissions.Select(i => i.PermissionId).Distinct().ToList();
                    if (pids.Any())
                    {
                        var permissions = await _permissionService.Query(i => pids.Contains(i.Id) );
                        var orderedPermissions = permissions.OrderBy(i => i.OrderSort).ToList();
                        var permissionTree = (from child in orderedPermissions
                                              where child.IsDeleted == false && child.IsHide == false
                                              orderby child.Id
                                              select new NavigationBar
                                              {
                                                  id = child.Id,
                                                  name = child.Name,
                                                  pid = child.Pid,
                                                  order = child.OrderSort,
                                                  IsHide = child.IsHide ?? false,
                                                  path = child.Code,
                                                  IsButton = child.IsButton,
                                                  Func = child.Func,
                                                  iconCls = child.Icon,
                                                  meta = new NavigationBarMeta
                                                  {
                                                      title = child.Name,
                                                      icon = child.Icon,
                                                      keepAlive = child.IskeepAlive ?? false,
                                                      requireAuth = true,
                                                      NoTabPage = child.IsHide ?? false
                                                  }
                                              }).ToList();
                        NavigationBar root = new NavigationBar
                        {
                            id = 0,
                            pid = 0,
                            name = "根节点",
                            order = 0,
                            path = "",
                            iconCls = "",
                            meta = new NavigationBarMeta()
                        };

                        permissionTree = permissionTree.OrderBy(i => i.order).ToList();
                        RecursionHelper.LoopToAppendChildren(permissionTree, root);
                        data.status = 200;
                        data.msg = "获取成功";
                        data.success = true;
                        data.response = root;
                    }
                }
            }
            return data;
        }

        /// <summary>
        /// 通过角色获取菜单
        /// </summary>
        /// <param name="rid"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<AssignShow>> GetPermissionIdByRoleId(long rid = 0)
        {
            var rmps = await _roleModulePermissionServices.Query(i => i.RoleId == rid);
            var permissionTrees = (from child in rmps
                                   orderby child.Id
                                   select child.PermissionId).ToList();
            var permissions = await _permissionService.Query();
            List<string> assignBtns = new List<string>();
            foreach (var permission in permissionTrees)
            {
                var perName = permissions.FirstOrDefault(d => d.IsButton && d.Id == permission)?.Name;
                if (!string.IsNullOrEmpty(perName))
                {
                    assignBtns.Add(permission.ObjToString());
                }
            }
            return Success(new AssignShow()
            {
                PermissionIds = permissionTrees,
                AssignBtns = assignBtns
            }, "获取成功");
        }

        /// <summary>
        /// 报错菜单分配权限
        /// </summary>
        /// <param name="assignView"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<MessageModel<string>> Assign([FromBody] AssignView assignView)
        {
            if (assignView.rid > 0)
            {
                // 开启事务
                try
                {
                    var old_rmps = await _roleModulePermissionServices.Query(i => i.RoleId == assignView.rid);

                    _unitOfWorkManage.BeginTran();
                    await _permissionService.Db.Deleteable<RoleModulePermission>(i => i.RoleId == assignView.rid).ExecuteCommandAsync();
                    var permissions = await _permissionService.Query();

                    List<RoleModulePermissionVo> new_rmps = new List<RoleModulePermissionVo>();
                    foreach (var pid in assignView.pids)
                    {
                        var mid = permissions.FirstOrDefault(i => i.Id == pid)?.Mid;
                        var find_old_rmps = old_rmps.FirstOrDefault(i => i.PermissionId == pid);

                        var roleModulePermission = new RoleModulePermissionVo()
                        {
                            IsDeleted = false,
                            RoleId = assignView.rid,
                            PermissionId = pid,
                            ModuleId = mid ?? 0,
                            CreateBy = find_old_rmps == null ? _user.Name : find_old_rmps.CreateBy,
                            CreateId = find_old_rmps == null ? _user.ID : find_old_rmps.CreateId,
                            CreateTime = find_old_rmps == null ? DateTime.Now : find_old_rmps.CreateTime,
                            ModifyBy = _user.Name,
                            ModifyId = _user.ID,
                            ModifyTime = DateTime.Now
                        };
                        new_rmps.Add(roleModulePermission);
                    }
                    if (new_rmps.Any())
                    {
                        await _roleModulePermissionServices.Add(_mapper.Map<List<RoleModulePermission>>( new_rmps));
                    }
                    _unitOfWorkManage.CommitTran();
                }
                catch (Exception)
                {
                    _unitOfWorkManage.RollbackTran();
                    throw;
                }
                _requirement.Permissions.Clear();
                return Success<string>("分配成功");
            }
            else
            {
                return Failed<string>("请选择要操作的角色");
            }
        }

        /// <summary>
        /// 根据数据库文件生成tsv文件，仅开发环境可用
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<string>> SaveDataToTsv()
        {
            var data = new MessageModel<string>();
            if (_env.IsDevelopment())
            {
                JsonSerializerSettings jsonSerializer = new JsonSerializerSettings()
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                    NullValueHandling = NullValueHandling.Ignore,
                    DateFormatHandling = DateFormatHandling.MicrosoftDateFormat
                };
                var list = await _permissionService.Query();
                var json = JsonConvert.SerializeObject(list, jsonSerializer);
                var file = Path.Combine(_env.ContentRootPath, "wwwroot", "SeedData", "Permission.tsv");
                FileHelper.WriteFile(file, json, Encoding.UTF8);

                data.success = true;
                data.msg = "生成成功，文件路径wwwroot/SeedData/Permission.tsv";
            }
            else
            {
                data.success = false;
                data.msg = "仅开发环境可用";
            }
            return data;
        }
    }

    public class AssignView
    {
        public List<long> pids { get; set; }
        public long rid { get; set; }
    }

    /// <summary>
    /// 授权参数
    /// </summary>
    public class AssignShow
    {
        /// <summary>
        /// 菜单id集合
        /// </summary>
        public List<long?>? PermissionIds { get; set; }
        /// <summary>
        /// 按钮id集合
        /// </summary>
        public List<string>? AssignBtns { get; set; }
    }
}
